#include "app_device.h"
#include "string.h"
#include "app_common.h"
#include "app_bt.h"
#include "log.h"
#include "app_serial.h"
#include <termios.h>
#include <unistd.h>



static char data_buff[100];
static int data_len = 0;
static char data_header[2] = {0xf1, 0xdd};

static void left_move_data(int move_offset)
{
    // 防御性检查 一般不会出现 ，但是也要检查
    if (move_offset > data_len)
    {
        move_offset = data_len;
    }
    // 移动
    memmove(data_buff, data_buff + move_offset, data_len - move_offset);
    // 减去长度
    data_len -= move_offset;
}

static int wait_ack(Device *device)
{    //必须保证 已经设置为非阻塞状态
    usleep(50*1000);
    char ack[4];
    read(device->fd, ack, 4);
    if(memcmp(ack, "OK\r\n", 4) == 0) 
    {
        return 0;
    }
    else 
    {   return -1;
    }
}

/**
 * 能否和蓝牙芯片联通  AT
 */
static int app_bt_status(Device *device )
{
    //发送 组合字符串 进行write
    write(device->fd, "AT\r\n", 4);
    return wait_ack(device);
}

static int app_bt_baudrate(Device *device, BTBaudRate baudrate)
{   
    char cmd[32]={0};
    sprintf(cmd, "AT+BAUD%c\r\n", baudrate);
    write(device->fd, cmd, strlen(cmd));

    return wait_ack(device);
}

/**
 * 重启蓝牙模块
 */
static int app_bt_reset(Device *device)  
{
    write(device->fd, "AT+RESET\r\n", 10);
    return wait_ack(device);
}

/**
 *  设置l网络id
 */
static int app_bt_set_netid(Device *device, char *netid)
{
    char cmd[32]={0};
    sprintf(cmd, "AT+NETID%s\r\n", netid);
    write(device->fd, cmd, strlen(cmd));
    return wait_ack(device);
}

static int app_bt_set_maddr(Device *device, char *maddr)
{
    char cmd[32]={0};
    sprintf(cmd, "AT+MADDR%s\r\n", maddr);
    write(device->fd, cmd, strlen(cmd));
    return wait_ack(device);
}

static int app_bt_set_name(Device *device, char *name)
{
    char cmd[32]={0};
    sprintf(cmd, "AT+NAME%s\r\n", name);
    write(device->fd, cmd, strlen(cmd));
    return wait_ack(device);
}



/**
 * @brief  设置蓝牙默认配置
 *     //1  有可能 主控芯片和蓝牙芯片  波特率不同 
    // 把主控芯片i改为非阻塞模式 
    // 先把主控芯片降为9600   
    //  和蓝牙芯片测试联通
    // 如果测试通过 说明 蓝牙芯片也是9600 则把蓝牙芯片改为115200 
       // 并重启l蓝牙芯片  等待2秒

    // 在把主控芯片改为115200 
    // 再做相关基本ii配置 

    // 再把主控芯片改为阻塞模式

 */
static int app_bt_set_default_config(Device *device)
{
    log_info("app_bt_set_default_config start  :");
    //1  有可能 主控芯片和蓝牙芯片  波特率不同 
    // 把主控芯片i改为非阻塞模式 
    app_serial_set_block(device,0);
    // 先把主控芯片降为9600 
    app_serial_set_baudrate(device,BR_9600); 
    //刷写生效
    tcflush(device->fd,TCIOFLUSH) ;
    //  和蓝牙芯片测试联通
    log_info("bt status %d", app_bt_status(device));
    if(app_bt_status(device)==0){
       // 如果测试通过 说明 蓝牙芯片也是9600 则把蓝牙芯片改为115200 
       app_bt_baudrate(device,BT_BAUD_115200);
       // 并重启l蓝牙芯片  等待2秒
       app_bt_reset(device);
       sleep(2);
    }


    // 在把主控芯片改为115200 
     app_serial_set_baudrate(device,BR_115200); 
     tcflush(device->fd,TCIOFLUSH);
    // 再做相关基本ii配置 
     log_info("bt status2 %d", app_bt_status(device));
     app_bt_set_name(device,"atguigu");
     app_bt_set_netid(device,"1234"); //1234老师专用 
     app_bt_set_maddr(device,"0066");

    // 再把主控芯片改为阻塞模式
    app_serial_set_block(device,1);
    tcflush(device->fd,TCIOFLUSH);

     log_info("app_bt_set_default_config end   ");
    return 0;

}


/**
 * 读取蓝牙中的数据  转换为 字节数组
 * 
 * 从设备读取数据后处理数据来满足网关应用的要求
 * 接收方得到数据1（4）：ok\r\n
 * 接收方得到数据2（3 + [2]）：f1 dd 07 23 23 ff ff 41 42 43
    f1 dd : 固定的头部
    07： 之后数据的长度（5-16之间）
    23 23：对端（发送方）的MADDR
    ff ff: 我的MADDR或ffff(群发)
    41 42 43：发送的数据
 * 处理后的数据格式：conn_type id_len msg_len id msg
 */
int app_bt_post_read(Device *device, char *data, int len)
{
    log_info("app_bt_post_read start :");
    app_common_log_info_hex(data, len);
    // 1 把数据拼接到缓存中
    memcpy(data_buff + data_len, data, len);
    data_len += len;

    //   针对缓存中的数据进行检查
    // 3  数据长度就不足 直接 返回
    if (data_len < 4)
    {
        return 0;
    }
    // 4  垃圾数据  在缓存数据中如果 找到OK 或者 f1 dd 之前的数据视为垃圾数据

    int i = 0; // 检查到的坐标
    for (i = 0; i < data_len; i++)
    {
        if (memcmp(data_buff + i, "OK", 2) == 0 || memcmp(data_buff + i, data_header, 2) == 0)
        {
            break;
        }
    }
    // 要把帧头的数据清理  从帧头（i位置）开始左移动 让帧头处于缓存的0位置
    left_move_data(i);
    // 5  判断缓存起始 如果是OK\r\n  清理掉 4个字节
    if (memcmp(data_buff, "OK\r\n", 4) == 0)
    {
        left_move_data(4);
    }
    // 6  判断缓存起始 如果是f1 dd 后面长度字节的值和后面的数据长度是否一致
    //  则说明是一个完整帧 -
    if (memcmp(data_buff, data_header, 2) == 0)
    { // a一个n完整帧至少是8个字节
      // b长度字节之后的数据长度 大于等于 长度字节的值
        if (data_len >= 8)
        {
            int data_remain_len =  data_buff[2]; // 一帧数据应该剩余的h长度
            if (data_len - 3 >= data_remain_len) // 一帧数据应该剩余的h长度 和实际g剩余的长度对比
            {   log_debug("data_remain_len:%d,data_len:%d",data_remain_len,data_len);
                app_common_log_info_hex(data_buff,data_len);
                // 提取数据做a转换  conn_type  id_len  msg_len  id  msg
                data[0] = CONN_TYPE_BT;
                data[1] = 2;                                       // id_len
                data[2] = data_remain_len - 4;                        // 长度字节的值-4(两个地址长度)
                memcpy(data + 3, data_buff + 3, 2);                // 对端地址作为id
                memcpy(data + 5, data_buff + 7, data_remain_len - 4); // 数据
                int data_len = data_remain_len + 3;
                // 从缓存中清理掉该数据   i替换data
                left_move_data(data_len);

                log_info("app_bt_post_read return  :");
                app_common_log_info_hex(data, data_len);
                return data_len;
            }
        }
    }
    return 0;
}



/*
  把字节数组转换为蓝牙数据
   * 准备向设备写前处理数据来满足蓝牙发送数据的要求
 * 当前data: conn_type id_len msg_len id msg (01 02 03 ff ff 11 22 33)
 * 蓝牙发送数据格式:
  示例：41 54 2b 4d 45 53 48 00 ff ff 41 42 43 0d 0a
        41 54 2b 4d 45 53 48 00： AT+MESH（固定头部）
        ff ff: 对端的MADDR（如果是FFFF代表群发）
        11 22 33: 要发送的数据（不超过12字节）
        0d 0a：\r\n（固定结尾）
*/
int app_bt_pre_write(Device *device, char *data, int len)
{
    log_info("app_bt_pre_write start  :");
    app_common_log_info_hex(data, len);
    char send_data_buff[32] = "AT+MESH";              // 帧头
    memcpy(send_data_buff + 8, data + 3, 2);          // 地址
    memcpy(send_data_buff + 10, data + 5, data[2]);   // n内容
    memcpy(send_data_buff + 10 + data[2], "\r\n", 2); // 结束符

    int send_data_len = 12 + data[2];            // 计算数据长度
    memcpy(data, send_data_buff, send_data_len); // 修改数据

    log_info("app_bt_pre_write return  :");
    app_common_log_info_hex(data, send_data_len);
    return send_data_len; // 返回发送长度
}


/**
 *  为设备进行蓝牙配置初始化
 * 1 设备的连接类型 赋值  conn_type =CONN_TYPE_BT
 *  2 为h设备装配 两个方法
 *          post_read
 *          pre_write
 *  3为蓝牙芯片设置默认值
 *
 *
 */
int app_bt_init(Device *device)
{ // 1 设备的连接类型 赋值  conn_type =CONN_TYPE_BT
    device->conn_type = CONN_TYPE_BT;
    //  2 为h设备装配 两个方法
    device->post_read = app_bt_post_read;
    device->pre_write = app_bt_pre_write;
    //  3 为蓝牙芯片设置默认值
    int ret= app_bt_set_default_config(device);
    return ret;
}